/**
 * 
 */
package org.jenkon.core;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.jenkon.commons.collection.iterator.ZipFileIterator;
import org.jenkon.commons.lang.filter.AndFilter;
import org.jenkon.commons.lang.filter.Filter;
import org.jenkon.core.filter.JarClassFilter;

/**
 * @author Jens Konopka
 * 
 */
public class JarClassIterator implements Iterator<Class<?>> {

	private final AndFilter<ZipEntry> andFilter = new AndFilter<ZipEntry>();
	private final ZipFileIterator zipFileIterator;
	private Class<?> current;

	public JarClassIterator(final File file) {
		this(get(file));
	}

	private static ZipFile get(final File file) {
		try {
			return new ZipFile(file);
		} catch (final Exception e) {
			throw new IllegalArgumentException(e);
		}
	}

	public JarClassIterator(final ZipFile zipFile) {
		this(zipFile, new ArrayList<Filter<ZipEntry>>());
	}

	public JarClassIterator(final ZipFile zipFile, final List<Filter<ZipEntry>> filter) {
		this.zipFileIterator = new ZipFileIterator(zipFile);
		filter.add(new JarClassFilter());
		andFilter.add(filter);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.Iterator#hasNext()
	 */
	@Override
	public boolean hasNext() {

		while (zipFileIterator.hasNext()) {

			final ZipEntry entry = zipFileIterator.next();
			
			if (andFilter.accept(entry)) {

				try {
					current = getClass(entry.getName());
					return true;
				} catch (final Throwable e) {
				}

			}

		}

		return false;

	}

	private static Class<?> getClass(final String name) throws ClassNotFoundException {
		return Class.forName(name.substring(0, name.length() - ".class".length()).replace("/", "."));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.Iterator#next()
	 */
	@Override
	public Class<?> next() {
		return current;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.util.Iterator#remove()
	 */
	@Override
	public void remove() {
		throw new UnsupportedOperationException("remove is not supported on " + getClass());
	}
}
